<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>RSADemo</title>
		<link rel="stylesheet" href="./css/bootstrap.min.css">
		<script src="./js/jquery3.5.1.js"></script>
		<script src="./js/bootstrap.min.js"></script>
		<script src="./js/jsencrypt.min.js"></script>
		<script src="js/jsencrypt.min.js"></script>
		<script src="js/aes.min.js"></script>
		<script type="text/javascript">
			$(function() {
				$("#rsaBtn").click(function() {
					var clientRsaPrivateKey = localStorage.getItem("client-rsa-private-key"); //客户端私钥
					const isEmptyKey = isEmpty(clientRsaPrivateKey);
					console.log("isEmptyKey is:" + isEmptyKey);
					if (isEmptyKey == true) {
						//生成公钥私钥
						const keypair = genetateKey();
						uploadPublicKey(keypair.getPublicKey());
						storePrivateKey(keypair.getPrivateKey());
					} else {
						console.log("私钥已存在：", clientRsaPrivateKey);
					}
				});
				$("#rsaServerBtn").click(function() {
					var serverRsapublicKey = localStorage.getItem("server-rsa-public-key"); //服务端公钥
					const isEmptyKey = isEmpty(serverRsapublicKey);
					console.log("isEmptyKey is:" + isEmptyKey);
					if (isEmptyKey == true) {
						const serverPublickey = fetchServerKey(1);
						console.log("服务端公钥为:" + serverPublickey);
						const isEmptyRSAKey = isEmpty(serverPublickey);
						if (isEmptyRSAKey == true) {
							console.log("获取服务端公钥失败");
						} else {
							//存储到本地
							localStorage.setItem("server-rsa-public-key", serverPublickey) //存储
						}
					}
					console.log("aesBtn clicked");
				});
				//获取AES密钥
				$("#aesBtn").click(function() {
					var serverAESKey = localStorage.getItem("server-aes-key"); //aes密钥
					const isEmptyKey = isEmpty(serverAESKey);
					console.log("isEmptyKey is:" + isEmptyKey);
					if (isEmptyKey == true) { //为空
						//获取AES密钥
						const aesEncryptKey = fetchServerKey(3);
						console.log("aes加密后密钥为:" + aesEncryptKey);
						var clientRsaPrivateKey = localStorage.getItem("client-rsa-private-key"); //客户端私钥
						// 实例化一个RSA对象
						const rsaInstance = new JSEncrypt();
						rsaInstance.setPrivateKey(clientRsaPrivateKey);
						const decryptedAESKey = rsaInstance.decrypt(aesEncryptKey);
						console.log("aes密钥为:" + decryptedAESKey);
						//存储到本地
						localStorage.setItem("server-aes-key", decryptedAESKey) //存储
					} else {

					}
				});
				$("#fetchTokenBtn").click(function() {
					const channel = "/security/test/request";
					const localToken = localStorage.getItem("userId-" + 3 + "-channel-" + channel);
					console.log("localToken is " + localToken);
					const token = fetchTokenRequest(channel);
					//存储到本地
					localStorage.setItem("userId-" + 3 + "-channel-" + "/security/test/request", token) //存储
				});	
				//sendBtn 发送消息
				$("#sendBtn").click(function() {
					const channel = "/security/test/request";
					var localToken = localStorage.getItem("userId-" + 3 + "-channel-" + channel);
					if(isEmpty(localToken)) {
						localToken = fetchTokenRequest(channel);
						localStorage.setItem("userId-" + 3 + "-channel-" + channel, localToken);
					}
					
					const message = $("#messge-input").val()
					console.log("message:" + message);
					var jsonData = {
						"message": message,
						"token": localToken,
						"userId" : 3,
						"channel": channel
					};
					//数据加密
					const jsonStr = JSON.stringify(jsonData)
					var secretKey = localStorage.getItem("server-aes-key"); //aes密钥
					const encryptData = encryptByAES(jsonStr, secretKey);
					console.log("encryptData is: " + encryptData);
					//发送数据
					const result = testRequest(encryptData);
					console.log("result:" + JSON.stringify(result));
				});
				$("#fetchTokenV1Btn").click(function() {
					const channel = "/security/test/request";
					var jsonData = {
						"userId": 3,
						"channel": channel
					};
					//数据加密
					const jsonStr = JSON.stringify(jsonData)
					var secretKey = localStorage.getItem("server-aes-key"); //aes密钥
					const encryptData = encryptByAES(jsonStr, secretKey);
					const token = fetchTokenV1Request(encryptData);
					console.log("encryptData is: " + encryptData);
					
					//存储到本地
					localStorage.setItem("token-userId-" + 3 + "-channel-" + "/security/test/request", token) //存储
				});	
			});
			//获取鉴权token加密版本
			function fetchTokenV1Request(encryptData) {
				var data = {
					"encryptString": encryptData,
					"channelId": 111
				};
				var token;
				$.ajax({
					async: false, //同步
					type: "post",
					url: "http://localhost:8080/user/generate/v1",
					contentType: 'application/json;charset=utf-8',
					data: JSON.stringify(data),
					success: function(result) {
						const resultJson = JSON.stringify(result);
						console.log("resultJson is " + resultJson);
						token = result.data.token;
						console.log("token is " + token);
					}
				});
				return token;
			}
			//获取鉴权token
			function fetchTokenRequest(channel) {
				var data = {
					"userId": 3,
					"channel": channel
				};
				var token;
				$.ajax({
					async: false, //同步
					type: "post",
					url: "http://localhost:8080/user/generate",
					contentType: 'application/json;charset=utf-8',
					data: JSON.stringify(data),
					success: function(result) {
						const resultJson = JSON.stringify(result);
						console.log("resultJson is " + resultJson);
						token = result.data.token;
						console.log("token is " + token);
					}
				});
				return token;
			}
			//发送请求数据
			function testRequest(encryptData) {
				var data = {
					"encryptString": encryptData,
					"channelId": "111"
				};
				var key;
				$.ajax({
					async: false, //同步
					type: "post",
					url: "http://localhost:8080/security/test/request",
					contentType: 'application/json;charset=utf-8',
					data: JSON.stringify(data),
					success: function(result) {
						const resultJson = JSON.stringify(result);
						console.log("resultJson is " + resultJson);
						const encryptData = result.data.encryptData;
						var secretKey = localStorage.getItem("server-aes-key"); //aes密钥
						const decryptData = decryptByAES(encryptData, secretKey)
						console.log("decryptData is " + decryptData)
						result.data = eval("(" + decryptData + ")"); //string转json
						key = result;
					},
					error: function (XMLHttpRequest, textStatus, errorThrown) {
						// 状态码
						console.log(XMLHttpRequest.status);
						// 状态码
						console.log(XMLHttpRequest.statusText);
						// 结果
						console.log(XMLHttpRequest.responseJSON);
						alert("请求失败,原因 : " + XMLHttpRequest.responseJSON.message)
					}
				});
				return key;
			}
			/**
			 * AES加密
			 * @param plainText 明文
			 * @param keyInBase64Str base64编码后的key
			 * @returns {string} base64编码后的密文
			 */
			function encryptByAES(plainText, keyInBase64Str) {
				let key = CryptoJS.enc.Base64.parse(keyInBase64Str);
				let encrypted = CryptoJS.AES.encrypt(plainText, key, {
					mode: CryptoJS.mode.ECB,
					padding: CryptoJS.pad.Pkcs7,
				});
				// 这里的encrypted不是字符串，而是一个CipherParams对象
				return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
			}

			/**
			 * AES解密
			 * @param cipherText 密文
			 * @param keyInBase64Str base64编码后的key
			 * @return 明文
			 */
			function decryptByAES(cipherText, keyInBase64Str) {
				let key = CryptoJS.enc.Base64.parse(keyInBase64Str);
				// 返回的是一个Word Array Object，其实就是Java里的字节数组
				let decrypted = CryptoJS.AES.decrypt(cipherText, key, {
					mode: CryptoJS.mode.ECB,
					padding: CryptoJS.pad.Pkcs7,
				});

				return decrypted.toString(CryptoJS.enc.Utf8);
			}

			//获取服务端密钥
			function fetchServerKey(type) {
				console.log("类型：", type);
				var data = {
					"channelId": "111",
					"type": type
				};
				var key;
				$.ajax({
					async: false, //同步
					type: "post",
					url: "http://localhost:8080/security/server/key",
					contentType: 'application/json;charset=utf-8',
					data: JSON.stringify(data),
					success: function(result) {
						const resultJson = JSON.stringify(result);
						console.log("resultJson is " + resultJson);
						key = result.data.key;
					}
				});
				return key;
			}

			//判断对象
			function isEmpty(obj) {
				if (obj == null || typeof obj === "undefined" || obj == "") {
					return true
				} else {
					return false
				}
			}
			//生成RSA密钥
			function genetateKey() {
				// 生成RSA密钥对
				const rsa = new JSEncrypt();
				const keypair = rsa.getKey();

				// 获取公钥和私钥
				const publicKey = keypair.getPublicKey();
				const privateKey = keypair.getPrivateKey();

				return keypair;
			}
			//私钥存储本地
			function storePrivateKey(privateKey) {
				localStorage.setItem("client-rsa-private-key", privateKey) //存储
				console.log("私钥：", privateKey);
			}
			//上传公钥到服务端
			function uploadPublicKey(publicKey) {
				console.log("公钥：", publicKey);
				var data = {
					"content": publicKey,
					"channelId": "111",
					"expireTime": "2024-08-01 00:00:00"
				};
				$.ajax({
					type: "post",
					url: "http://localhost:8080/security/rsa/client/public/key",
					contentType: 'application/json;charset=utf-8',
					data: JSON.stringify(data),
					success: function(d) {
						console.log(d);
					}
				});
			}
		</script>
	</head>

	<body>
		<div class="container">
			<div class="row">
				<div class="col" style="padding-left: 0;">
					<button type="button" class="btn btn-primary" id="rsaBtn">1-上传RSA公钥</button>
				</div>
				<div class="col" style="text-align: center;">
					<button type="button" class="btn btn-primary" id="rsaServerBtn">2-请求服务端RSA公钥</button>
				</div>
				<div class="col" style="text-align: right;">
					<button type="button" class="btn btn-primary" id="aesBtn">3-请求AES证书</button>
				</div>
			</div>
			<div>
				<br />
			</div>
			<div class="row">
				<div class="col" style="padding-left: 0;">
					<button type="button" class="btn btn-primary" id="fetchTokenBtn">4-获取token</button>
				</div>
				<div class="col" style="text-align: center;">
					<button type="button" class="btn btn-primary" id="fetchTokenV1Btn">5-获取token加密版本</button>
				</div>
			</div>
			<div>
				<br />
			</div>
			<div class="row">
				<div class="col" style="padding-left: 0;padding-right: 0;">
					<input type="text" class="form-control" placeholder="请输入消息内容" id="messge-input">
				</div>
				<div class="col" style="text-align: right;">
					<button type="button" class="btn btn-primary" id="sendBtn">发送消息</button>
				</div>
			</div>
		</div>
	</body>
</html>